package com.yunke.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yunke.common.exception.BusinessException;
import com.yunke.entity.YunkeConfig;
import com.yunke.entity.dto.YunkeConfigDto;
import com.yunke.entity.vo.YunkeConfigVo;
import com.yunke.mapper.YunkeConfigMapper;
import com.yunke.service.YunkeConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

/**
 * 系统配置服务实现类
 * 
 * @author yunke
 * @since 1.0.0
 */
@Service
public class YunkeConfigServiceImpl extends ServiceImpl<YunkeConfigMapper, YunkeConfig> implements YunkeConfigService {

    @Autowired
    private YunkeConfigMapper configMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean createConfig(YunkeConfigDto configDto) {
        // 验证配置键名是否存在
        if (configMapper.checkConfigKeyExists(configDto.getConfigKey(), null) > 0) {
            throw new BusinessException("配置键名已存在");
        }

        // 验证配置值
        if (!validateConfigValue(configDto.getConfigKey(), configDto.getConfigValue())) {
            throw new BusinessException("配置值格式不正确");
        }

        YunkeConfig config = BeanUtil.copyProperties(configDto, YunkeConfig.class);
        config.setCreateTime(System.currentTimeMillis());
        config.setUpdateTime(System.currentTimeMillis());
        config.setStatus(0);

        // 设置默认值
        if (config.getIsSystem() == null) {
            config.setIsSystem(false);
        }
        if (config.getIsRequired() == null) {
            config.setIsRequired(false);
        }
        if (config.getIsEnabled() == null) {
            config.setIsEnabled(true);
        }
        if (config.getIsSensitive() == null) {
            config.setIsSensitive(false);
        }
        if (config.getSortWeight() == null) {
            config.setSortWeight(0);
        }

        return save(config);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateConfig(YunkeConfigDto configDto) {
        YunkeConfig existConfig = getById(configDto.getId());
        if (existConfig == null) {
            throw new BusinessException("配置不存在");
        }

        // 系统配置不能修改键名
        if (existConfig.getIsSystem() && !existConfig.getConfigKey().equals(configDto.getConfigKey())) {
            throw new BusinessException("系统配置不能修改键名");
        }

        // 验证配置键名是否存在
        if (configMapper.checkConfigKeyExists(configDto.getConfigKey(), configDto.getId()) > 0) {
            throw new BusinessException("配置键名已存在");
        }

        // 验证配置值
        if (!validateConfigValue(configDto.getConfigKey(), configDto.getConfigValue())) {
            throw new BusinessException("配置值格式不正确");
        }

        YunkeConfig config = BeanUtil.copyProperties(configDto, YunkeConfig.class);
        config.setUpdateTime(System.currentTimeMillis());

        return updateById(config);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteConfig(Long id) {
        YunkeConfig config = getById(id);
        if (config == null) {
            throw new BusinessException("配置不存在");
        }

        if (config.getIsSystem()) {
            throw new BusinessException("系统配置不能删除");
        }

        config.setStatus(1);
        config.setUpdateTime(System.currentTimeMillis());
        return updateById(config);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteConfigs(List<Long> ids) {
        return configMapper.deleteConfigByIds(ids) > 0;
    }

    @Override
    public IPage<YunkeConfigVo> getConfigPage(Integer current, Integer size,
                                             String configCategory, String configGroup,
                                             String configName, Boolean isSystem, Boolean isEnabled) {
        Page<YunkeConfigVo> page = new Page<>(current, size);
        return configMapper.selectConfigPage(page, configCategory, configGroup, configName, isSystem, isEnabled);
    }

    @Override
    public YunkeConfigVo getConfigById(Long id) {
        YunkeConfig config = getById(id);
        if (config == null) {
            return null;
        }

        YunkeConfigVo configVo = BeanUtil.copyProperties(config, YunkeConfigVo.class);
        buildConfigVo(configVo);
        return configVo;
    }

    @Override
    public YunkeConfigVo getConfigByKey(String configKey) {
        return configMapper.selectConfigByKey(configKey);
    }

    @Override
    public List<YunkeConfigVo> getConfigByCategory(String configCategory, Boolean isEnabled) {
        return configMapper.selectConfigByCategory(configCategory, isEnabled);
    }

    @Override
    public List<YunkeConfigVo> getConfigByGroup(String configGroup, Boolean isEnabled) {
        return configMapper.selectConfigByGroup(configGroup, isEnabled);
    }

    @Override
    public List<YunkeConfigVo> getSystemConfigs(Boolean isEnabled) {
        return configMapper.selectSystemConfigs(isEnabled);
    }

    @Override
    public List<YunkeConfigVo> getUserVisibleConfigs(Boolean isEnabled) {
        return configMapper.selectUserVisibleConfigs(isEnabled);
    }

    @Override
    public List<String> getConfigCategories() {
        return configMapper.selectConfigCategories();
    }

    @Override
    public List<String> getConfigGroups(String configCategory) {
        return configMapper.selectConfigGroups(configCategory);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean enableConfig(Long id) {
        YunkeConfig config = getById(id);
        if (config == null) {
            throw new BusinessException("配置不存在");
        }

        config.setIsEnabled(true);
        config.setUpdateTime(System.currentTimeMillis());
        return updateById(config);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean disableConfig(Long id) {
        YunkeConfig config = getById(id);
        if (config == null) {
            throw new BusinessException("配置不存在");
        }

        if (config.getIsRequired()) {
            throw new BusinessException("必填配置不能禁用");
        }

        config.setIsEnabled(false);
        config.setUpdateTime(System.currentTimeMillis());
        return updateById(config);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateConfigStatus(List<Long> ids, Integer status) {
        return configMapper.updateConfigStatus(ids, status) > 0;
    }

    @Override
    public String getConfigValue(String configKey) {
        YunkeConfig config = getOne(new LambdaQueryWrapper<YunkeConfig>()
                .eq(YunkeConfig::getConfigKey, configKey)
                .eq(YunkeConfig::getIsEnabled, true)
                .eq(YunkeConfig::getStatus, 0));
        return config != null ? config.getConfigValue() : null;
    }

    @Override
    public String getConfigValue(String configKey, String defaultValue) {
        String value = getConfigValue(configKey);
        return StrUtil.isNotBlank(value) ? value : defaultValue;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateConfigValue(String configKey, String configValue) {
        YunkeConfig config = getOne(new LambdaQueryWrapper<YunkeConfig>()
                .eq(YunkeConfig::getConfigKey, configKey)
                .eq(YunkeConfig::getStatus, 0));

        if (config == null) {
            throw new BusinessException("配置不存在");
        }

        // 验证配置值
        if (!validateConfigValue(configKey, configValue)) {
            throw new BusinessException("配置值格式不正确");
        }

        config.setConfigValue(configValue);
        config.setUpdateTime(System.currentTimeMillis());
        return updateById(config);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateConfigValues(Map<String, String> configMap) {
        for (Map.Entry<String, String> entry : configMap.entrySet()) {
            updateConfigValue(entry.getKey(), entry.getValue());
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean resetConfigToDefault(String configKey) {
        YunkeConfig config = getOne(new LambdaQueryWrapper<YunkeConfig>()
                .eq(YunkeConfig::getConfigKey, configKey)
                .eq(YunkeConfig::getStatus, 0));

        if (config == null) {
            throw new BusinessException("配置不存在");
        }

        if (StrUtil.isBlank(config.getDefaultValue())) {
            throw new BusinessException("该配置没有默认值");
        }

        config.setConfigValue(config.getDefaultValue());
        config.setUpdateTime(System.currentTimeMillis());
        return updateById(config);
    }

    @Override
    public List<YunkeConfigVo> exportConfigs(String configCategory, Boolean isSystem) {
        LambdaQueryWrapper<YunkeConfig> wrapper = new LambdaQueryWrapper<YunkeConfig>()
                .eq(YunkeConfig::getStatus, 0);

        if (StrUtil.isNotBlank(configCategory)) {
            wrapper.eq(YunkeConfig::getConfigCategory, configCategory);
        }
        if (isSystem != null) {
            wrapper.eq(YunkeConfig::getIsSystem, isSystem);
        }

        List<YunkeConfig> configs = list(wrapper);
        return BeanUtil.copyToList(configs, YunkeConfigVo.class);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean importConfigs(List<YunkeConfigDto> configList) {
        for (YunkeConfigDto configDto : configList) {
            if (configMapper.checkConfigKeyExists(configDto.getConfigKey(), null) == 0) {
                createConfig(configDto);
            }
        }
        return true;
    }

    @Override
    public boolean validateConfigValue(String configKey, String configValue) {
        YunkeConfig config = getOne(new LambdaQueryWrapper<YunkeConfig>()
                .eq(YunkeConfig::getConfigKey, configKey)
                .eq(YunkeConfig::getStatus, 0));

        if (config == null) {
            return true;
        }

        // 必填验证
        if (config.getIsRequired() && StrUtil.isBlank(configValue)) {
            return false;
        }

        // 类型验证
        try {
            switch (config.getConfigType()) {
                case 2: // 数字
                    Double.parseDouble(configValue);
                    break;
                case 3: // 布尔
                    if (!"true".equals(configValue) && !"false".equals(configValue)) {
                        return false;
                    }
                    break;
                case 4: // JSON
                    if (StrUtil.isNotBlank(configValue)) {
                        JSONUtil.parse(configValue);
                    }
                    break;
            }
        } catch (Exception e) {
            return false;
        }

        // 验证规则验证
        if (StrUtil.isNotBlank(config.getValidationRule())) {
            try {
                Pattern pattern = Pattern.compile(config.getValidationRule());
                if (!pattern.matcher(configValue).matches()) {
                    return false;
                }
            } catch (Exception e) {
                return false;
            }
        }

        return true;
    }

    @Override
    public long countConfigs(String configCategory, Boolean isSystem, Boolean isEnabled) {
        return configMapper.countConfigs(configCategory, isSystem, isEnabled);
    }

    /**
     * 构建配置VO对象
     */
    private void buildConfigVo(YunkeConfigVo configVo) {
        // 配置类型描述
        switch (configVo.getConfigType()) {
            case 1:
                configVo.setConfigTypeDesc("字符串");
                break;
            case 2:
                configVo.setConfigTypeDesc("数字");
                break;
            case 3:
                configVo.setConfigTypeDesc("布尔");
                break;
            case 4:
                configVo.setConfigTypeDesc("JSON");
                break;
            case 5:
                configVo.setConfigTypeDesc("文件路径");
                break;
        }

        // 系统配置描述
        configVo.setIsSystemDesc(configVo.getIsSystem() ? "是" : "否");

        // 必填描述
        configVo.setIsRequiredDesc(configVo.getIsRequired() ? "是" : "否");

        // 启用状态描述
        configVo.setIsEnabledDesc(configVo.getIsEnabled() ? "启用" : "禁用");

        // 敏感信息描述
        configVo.setIsSensitiveDesc(configVo.getIsSensitive() ? "是" : "否");

        // 状态描述
        configVo.setStatusDesc(configVo.getStatus() == 0 ? "正常" : "删除");
    }
} 